package pimmodel;

import java.util.Date;
import java.util.Observer;

import pimgui.PimGui;


/**
 * 
 * Klasse Termin:<br>
 * Die Klasse Termin beinhaltet alle wesentlichen Termindaten und <br>
 * die entsprechenden Verwaltungsmethoden.
 * 
 * @authors (Torsten Mansfeld, Thomas Schoenfeld)
 * @version (20120908_01)
 * 
 */

public class Termin extends PimDaten implements ITermin {

	// Serialisierungs-UID
	private static	final	long		serialVersionUID		= 1L;
	
	
	
	// Meldungskonstanten
	private static	final	String		IKONTAKT				= "Das uebergebene Objekt ist nicht vom Typ IKontakt.";
	private static	final	String		ITERMIN					= "Das uebergebene Objekt ist nicht vom Typ ITermin.";
	private	static	final	String		DATUM					= "Das uebergebene Objekt ist nicht vom Typ Date.";
	private static	final	String		BESCHREIBUNG			= "Die uebergebene Beschreibung ist ist kein gueltiger String.";
	private	static	final	String		WIEDERHOLUNGSINTERVALL	= "Die uebergebene Wiederholungsintervall ist negativ.";
	private	static	final	String		ERINNERUNGSZEITPUNKT	= "Die uebergebene Erinnerungszeitpunkt ist negativ.";
	
	
	
	// Instanzvariablen
	private					boolean 	istErinnerung;
	private					boolean 	istWiederholung;
	private					int 		erinnerungszeitpunkt;
	private					int 		wiederholungsintervall;
	private					String		beschreibung;
	private					Date		datum;
	private					Observer	observer;
	private					IAdresse	adresse;
	
	
	
	/**
	 * Standardkonstruktor der Klasse Termin
	 */
	public Termin() {

		this( "Betreff" );
		
	}
	
	/**
	 * Konstruktor der Klasse Termin:<br>
	 * @param	name					Kurzbeschreibung Termin
	 */
	public Termin( String name ) {
		
		super( name );
		this.istErinnerung				= true;
		this.istWiederholung			= false;
		this.erinnerungszeitpunkt		= 1; // 1 was?
		this.wiederholungsintervall		= 7;
		this.beschreibung				= "";
		this.datum						= new Date();
		this.adresse					= new Adresse( "", "", "", "Initial", "" );
		
	}
	
	/**
	 * Konstruktor der Klasse Termin:<br>
	 * @param	name					Kurzbeschreibung Termin
	 * @param	datum					Datum
	 * @param	beschreibung			Beschreibung
	 * @param	istWiederholung			ob Termin wiederholt werden soll
	 * @param	wiederholungsintervall	in welchem Intervall wiederholt werden soll
	 * @param	istErinnerung			ob an den Termin erinnert werden soll
	 * @param	erinnerungszeitpunkt	wann erinnert werden soll
	 * @param	o						Observer-Objekt
	 */
	
	public Termin(	final String name, final String beschreibung, final Date datum,
					final boolean istWiederholung, final int wiederholungsintervall,
					final boolean istErinnerung, final int erinnerungszeitpunkt, final Observer o ) {
		
		this( name );				
		
		setErinnerung( istErinnerung );
		setWiederholung( istWiederholung );
		setErinnerungszeitpunkt( erinnerungszeitpunkt );
		setWiederholungsintervall( wiederholungsintervall );
		setBeschreibung( beschreibung );
		setDatum( datum );
		
		this.observer	= o;
		
		if ( this.observer != null )
			this.addObserver( this.observer );
		
	}
	
	/**
	 * Konstruktor der Klasse Termin:<br>
	 * @param	name					Kurzbeschreibung Termin
	 * @param	datum					Datum
	 * @param	beschreibung			Beschreibung
	 * @param	istWiederholung			ob Termin wiederholt werden soll
	 * @param	wiederholungsintervall	in welchem Intervall wiederholt werden soll
	 * @param	istErinnerung			ob an den Termin erinnert werden soll
	 * @param	erinnerungszeitpunkt	wann erinnert werden soll
	 * @param	IKontakt				Kontaktdaten fuer Adresse
	 * @param	o						Observer-Objekt
	 * 
	 * @throws	IllegalArgumentException falls das uebergebene Objekt nicht vom Typ IKontakt ist.
	 */
	
	public Termin(	final String name, final String beschreibung, final Date datum,
					final boolean istWiederholung, final int wiederholungsintervall,
					final boolean istErinnerung, final	int erinnerungszeitpunkt,
					final IKontakt kombinierterkontakt, final Observer o ) {
		
		this( name, beschreibung, datum, istWiederholung, wiederholungsintervall, istErinnerung, erinnerungszeitpunkt, o );
		
		if ( !( kombinierterkontakt instanceof IKontakt ) )
			throw new IllegalArgumentException( IKONTAKT );
		
		// Konstruktor Adresse: Adresse( String strasse, String hausnummer, String plz, String ort, String land );
		this.adresse = new Adresse( kombinierterkontakt.getStrasse(),
									kombinierterkontakt.getHausnummer(), "",
									kombinierterkontakt.getOrt(), "");		
		
	}		
	
	/**
	 * Konstruktor der Klasse Termin:<br>
	 * @param	name					Kurzbeschreibung Termin
	 * @param	beschreibung			Beschreibung
	 * @param	datum					Datum
	 * @param	strasse					Strasse
	 * @param	hausnummer				Hausnummer
	 * @param	ort						Ort
	 * @param	istWiederholung			ob Termin wiederholt werden soll
	 * @param	wiederholungsintervall	in welchem Intervall wiederholt werden soll
	 * @param	istErinnerung			ob an den Termin erinnert werden soll
	 * @param	erinnerungszeitpunkt	wann erinnert werden soll
	 * @param	IKontakt				Kontaktdaten fuer Adresse
	 * @param	o						Observer-Objekt
	 */
	public Termin(	final String name, final String beschreibung, final Date datum,
					final String strasse, final String hausnummer, final String ort, 
					final boolean istWiederholung, final int wiederholungsintervall,
					final boolean istErinnerung, final int erinnerungszeitpunkt, Observer o ) {
		
		this( name, beschreibung, datum, istWiederholung, wiederholungsintervall, istErinnerung, erinnerungszeitpunkt, o );
		
		// Konstruktor Adresse: Adresse( String strasse, String hausnummer, String plz, String ort, String land );
		this.adresse = new Adresse( strasse, hausnummer, "", ort, "" );		
		
	}

	/**
	 * Kopierkonstruktor der Klasse Termin:<br>
	 * @param	termin					der zu kopierende Termin
	 */
	public Termin( ITermin termin ) {
		
		if ( !( termin instanceof ITermin ) )
			throw new IllegalArgumentException( ITERMIN );
		
		// Konstruktor Adresse: Adresse( String strasse, String hausnummer, String plz, String ort, String land );
		this.adresse = new Adresse( termin.getStrasse(), termin.getHausnummer(), "", termin.getOrt(), "" );		
		
		setName( termin.getName() );
		setErinnerung( termin.getErinnerung() );
		setWiederholung( termin.getWiederholung() );
		setErinnerungszeitpunkt( termin.getErinnerungszeitpunkt() );
		setWiederholungsintervall( termin.getWiederholungsintervall() );
		setBeschreibung( termin.getBeschreibung() );
		setDatum( termin.getDatum() );
		
		this.observer = ( ( Termin )termin ).observer;
		
		if ( this.observer != null )
			this.addObserver( this.observer );
		
	}
	
	
	// Getter und Setter Methoden
	
	/* (non-Javadoc)
	 * @see pimmodel.ITermin#getDatum()
	 */
	@Override
	public Date getDatum() {
		
		return this.datum;
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.ITermin#setDatum(java.util.Date)
	 */
	@Override
	public void setDatum( final Date datum ) {
		
		if ( !( datum instanceof Date ) )
			throw new IllegalArgumentException( DATUM );
		
		this.datum = datum;
		this.setChanged();
		this.notifyObservers(this.datum);
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.ITermin#getBeschreibung()
	 */	
	@Override
	public String getBeschreibung() {
		
		return this.beschreibung;
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.ITermin#setBeschreibung(java.lang.String)
	 */	
	@Override
	public void setBeschreibung( final String beschreibung ) {
		
		if ( !( beschreibung instanceof String ) )
			throw new IllegalArgumentException( BESCHREIBUNG );

		this.beschreibung = beschreibung.trim();
		this.setChanged();
		this.notifyObservers(this.beschreibung);
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.ITermin#getStrasse()
	 */	
	@Override
	public String getStrasse() {
		
		return this.adresse.getStrasse();
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.ITermin#setStrasse(java.lang.String)
	 */	
	@Override
	public void setStrasse( final String strasse ) {
		
		this.adresse.setStrasse( strasse );
		this.setChanged();
		this.notifyObservers( this.adresse.getStrasse() );
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.ITermin#getHausnummer()
	 */	
	@Override
	public String getHausnummer() {
		
		return this.adresse.getHausnummer();
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.ITermin#setHausnummer(int)
	 */
	@Override
	public void setHausnummer(final String hausnummer) {
				
		this.adresse.setHausnummer( hausnummer );
		this.setChanged();
		this.notifyObservers( this.adresse.getHausnummer() );
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.ITermin#getOrt()
	 */
	@Override
	public String getOrt() {
		
		return this.adresse.getOrt();
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.ITermin#setOrt(java.lang.String)
	 */	
	@Override
	public void setOrt( final String ort ) {
		
		this.adresse.setOrt( ort );
		this.setChanged();
		this.notifyObservers( this.adresse.getOrt () );
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.ITermin#getAdresse()
	 */
	@Override
	public IAdresse getAdresse() {
		
		return new Adresse( this.adresse );
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.ITermin#setAdresse(pimmodel.IAdresse)
	 */	
	@Override
	public void setAdresse( final IAdresse adresse ) {
		
		this.adresse = new Adresse ( adresse );
		this.setChanged();
		this.notifyObservers( this.adresse.getOrt () );
		
	}
	
	
	/* (non-Javadoc)
	 * @see pimmodel.ITermin#getWiederholung()
	 */	
	@Override
	public boolean getWiederholung() {
		
		return this.istWiederholung;
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.ITermin#setWiederholung(boolean)
	 */	
	@Override
	public void setWiederholung( final boolean wiederholung ) {
		
		this.istWiederholung = wiederholung;
		this.setChanged();
		this.notifyObservers( wiederholung );
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.ITermin#getWiederholungsintervall()
	 */	
	@Override
	public int getWiederholungsintervall() {
		
		return this.wiederholungsintervall;
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.ITermin#setWiederholungsintervall(int)
	 */	
	@Override
	public void setWiederholungsintervall( final int wiederholungsintervall ) {
		
		if ( wiederholungsintervall < 0 )
			throw new IllegalArgumentException( WIEDERHOLUNGSINTERVALL );
		
		this.wiederholungsintervall = wiederholungsintervall;
		this.setChanged();
		this.notifyObservers( wiederholungsintervall );
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.ITermin#getErinnerung()
	 */
	@Override
	public boolean getErinnerung() {
		
		return this.istErinnerung;
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.ITermin#setErinnerung(boolean)
	 */	
	@Override
	public void setErinnerung( final boolean erinnerung ) {
		
		this.istErinnerung = erinnerung;
		this.setChanged();
		this.notifyObservers(erinnerung);
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.ITermin#getErinnerungszeitpunkt()
	 */	
	@Override
	public int getErinnerungszeitpunkt() {
		
		return this.erinnerungszeitpunkt;
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.ITermin#setErinnerungszeitpunkt(int)
	 */	
	@Override
	public void setErinnerungszeitpunkt( final int erinnerungszeitpunkt ) {
		
		if ( erinnerungszeitpunkt < 0 )
			throw new IllegalArgumentException( ERINNERUNGSZEITPUNKT );
		
		this.erinnerungszeitpunkt = erinnerungszeitpunkt;
		this.setChanged();
		this.notifyObservers(erinnerungszeitpunkt);
		
	}

	
	
	// sonstige Methoden

	/* (non-Javadoc)
	 * @see pimmodel.ITermin#toString()
	 */
	@Override
	public String toString() {
		String dateString = String.format("%1$td-%1$tm-%1$tY", this.getDatum());
		String ausgabe="";
		ausgabe= PimGui.getResourceBundle().getString("ter_1")+
				PimGui.getResourceBundle().getString("ter_2") +"       " +this.getName()+PimGui.getResourceBundle().getString("Kon_1")+
			    PimGui.getResourceBundle().getString("ter_3")+ "              "+this.getBeschreibung()+PimGui.getResourceBundle().getString("Kon_1")+
			    PimGui.getResourceBundle().getString("ter_4")+ "                        "+dateString+PimGui.getResourceBundle().getString("Kon_1")+
			     PimGui.getResourceBundle().getString("Kon_s") + "   "+this.getStrasse()+PimGui.getResourceBundle().getString("Kon_1")+
			      PimGui.getResourceBundle().getString("Kon_h")+ "       "+this.getHausnummer()+PimGui.getResourceBundle().getString("Kon_1")+
			      PimGui.getResourceBundle().getString("Kon_o")+ "        "+this.getOrt()+PimGui.getResourceBundle().getString("Kon_1");
		if (this.getWiederholung()==true){
			if (this.getWiederholungsintervall()==1){
				ausgabe+=PimGui.getResourceBundle().getString("ter_5")+PimGui.getResourceBundle().getString("Kon_1");
			}else if (this.getWiederholungsintervall()==7){
				ausgabe+=PimGui.getResourceBundle().getString("ter_6")+PimGui.getResourceBundle().getString("Kon_1");
			}else if (this.getWiederholungsintervall()==30){
				ausgabe+=PimGui.getResourceBundle().getString("ter_7")+PimGui.getResourceBundle().getString("Kon_1");
			}else if (this.getWiederholungsintervall()==100){
				ausgabe+=PimGui.getResourceBundle().getString("ter_8")+PimGui.getResourceBundle().getString("Kon_1");
			}
		}else{
			ausgabe+=PimGui.getResourceBundle().getString("ter_9")+PimGui.getResourceBundle().getString("Kon_1");
		}
		
		if (this.getErinnerung()==true){
			if (this.getErinnerungszeitpunkt()==1){
				ausgabe+=PimGui.getResourceBundle().getString("term_1")+PimGui.getResourceBundle().getString("Kon_1");
			}else if (this.getWiederholungsintervall()==7){
				ausgabe+=PimGui.getResourceBundle().getString("term_2")+PimGui.getResourceBundle().getString("Kon_1");
			}else if (this.getWiederholungsintervall()==3){
				ausgabe+=PimGui.getResourceBundle().getString("term_3")+PimGui.getResourceBundle().getString("Kon_1");
			}
		}else{
			ausgabe+=PimGui.getResourceBundle().getString("term_4")+PimGui.getResourceBundle().getString("Kon_1");
		}
		
		return ausgabe;
	}

	/* (non-Javadoc)
	 * @see pimmodel.ITermin#hashCode()
	 */
	@Override
	public int hashCode() {
		
		final int prime = 31;
		
		int result = super.hashCode();
		
		result = prime * result + ( ( adresse == null ) ? 0 : adresse.hashCode() );
		result = prime * result	+ ( ( beschreibung == null ) ? 0 : beschreibung.hashCode() );
		result = prime * result + ( ( datum == null ) ? 0 : datum.hashCode() );
		result = prime * result + erinnerungszeitpunkt;
		result = prime * result + ( istErinnerung ? 1231 : 1237 );
		result = prime * result + ( istWiederholung ? 1231 : 1237 );
		result = prime * result + wiederholungsintervall;
		
		return result;
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.ITermin#equals(java.lang.Object)
	 */
	@Override
	public boolean equals( final Object obj ) {
		
		if ( this == obj )
			return true;
		
		if ( !super.equals( obj ) )
			return false;
		
		if ( getClass() != obj.getClass() )
			return false;
		
		Termin other = ( Termin ) obj;
		
		if ( adresse == null ) {
			if ( other.adresse != null )
				return false;
		}
		else if ( !adresse.equals( other.adresse) )
			return false;
		
		if ( beschreibung == null ) {
			if ( other.beschreibung != null )
				return false;
		}
		else if ( !beschreibung.equals( other.beschreibung ) )
			return false;
		
		if ( datum == null ) {
			if ( other.datum != null )
				return false;
		}
		else if ( !datum.equals( other.datum ) )
			return false;
		
		if ( erinnerungszeitpunkt != other.erinnerungszeitpunkt )
			return false;
		
		if ( istErinnerung != other.istErinnerung )
			return false;
		
		if ( istWiederholung != other.istWiederholung )
			return false;
		
		if ( wiederholungsintervall != other.wiederholungsintervall )
			return false;
		
		return true;
		
	}

	/**
	 * compareTo		erlaubt einen lexikographischen Groessenvergleich mit einem anderen Termin
	 * 
	 * @param	kontakt	der zu vergleichende Termin
	 * 
	 * @return			-1, falls der aktuelle Termin lexikographisch kleiner,<br>
	 * 				 	 1, falls er groesser und<br>
	 * 				 	 0, gleich dem uebergebenen Termin ist
	 * 
	 * @throws			IllegalArgumentException falls das uebergebene Objekt nicht vom Typ ITermin ist.
	 */
	@Override
	public int compareTo( final ITermin termin ) {
		
		if ( ! ( termin instanceof ITermin ) )
			throw new IllegalArgumentException( ITERMIN );

		if ( this.datum.compareTo( termin.getDatum() ) < 0 )
			return -1;
		if ( this.datum.compareTo( termin.getDatum() ) > 0 )
			return 1;		
		if ( this.getName().compareTo( termin.getName() ) < 0 )
			return -1;
		if ( this.getName().compareTo( termin.getName() ) > 0 )
			return 1;
		if ( this.getOrt().compareTo( termin.getOrt() ) < 0 )
			return -1;
		if ( this.getOrt().compareTo( termin.getOrt() ) > 0 )
			return 1;
		
		return 0;
		
	}	
	
}
